import { worker } from "workerpool";
import { JSDOM } from "jsdom";
import fs from "fs/promises";
import path from "path";

// 初始化 JSDOM 环境
const dom = new JSDOM(
  `<!DOCTYPE html><body><div id="container"></div></body>`,
  {
    pretendToBeVisual: true,
    resources: "usable",
  }
);
const { window } = dom;
const { document } = window;
const { DOMParser, XMLSerializer } = window;

// 扩展全局类型
declare global {
  interface Window {
    mermaid: any;
  }
  interface SVGElement {
    getBBox: () => DOMRect;
    getComputedTextLength: () => number;
  }
}

// 核心增强系统
class DOMEnhancer {
  static init() {
    this.proxyCreateElements();
    this.injectNamespaceSupport();
    this.setupSerialization();
    this.injectGlobalStyles();
  }

  // 代理元素创建方法
  private static proxyCreateElements() {
    // 代理 createElementNS
    const originalCreateNS = document.createElementNS.bind(document);
    document.createElementNS = (ns: string, name: string) => {
      const element = originalCreateNS(ns, name);

      // 强制填充 foreignObject 内容
      if (name === "foreignObject") {
        const div = document.createElementNS(
          "http://www.w3.org/1999/xhtml",
          "div"
        );
        div.style.cssText = `
          font: 14px Arial !important;
          color: #333 !important;
          padding: 8px;
          visibility: visible !important;
        `;

        // 动态内容绑定
        Object.defineProperty(element, "textContent", {
          set: (value) => {
            div.textContent = value;
            return value;
          },
          get: () => div.textContent,
        });

        element.appendChild(div);
      }

      return this.enhanceElement(element);
    };

    // 代理 innerHTML 设置
    const originalInnerHTML = Object.getOwnPropertyDescriptor(
      Element.prototype,
      "innerHTML"
    )!;
    Object.defineProperty(Element.prototype, "innerHTML", {
      set: function (value) {
        originalInnerHTML.set!.call(this, value);
        Array.from(this.children).forEach(DOMEnhancer.enhanceElement);
      },
    });
  }

  // 增强元素属性
  private static enhanceElement(element: Element): Element {
    // SVG 增强
    if (element.namespaceURI === "http://www.w3.org/2000/svg") {
      const svgEl = element as unknown as SVGElement;

      // 布局测量
      svgEl.getBBox = () => {
        if (element.hasAttribute("width") && element.hasAttribute("height")) {
          return new window.DOMRect(
            0,
            0,
            parseFloat(element.getAttribute("width")!),
            parseFloat(element.getAttribute("height")!)
          );
        }
        return new window.DOMRect(0, 0, 800, 600);
      };

      // 文本测量
      if (["text", "tspan"].includes(element.tagName.toLowerCase())) {
        svgEl.getComputedTextLength = () =>
          (element.textContent?.length || 0) * 8;
      }
    }

    // HTML 增强
    if (element instanceof window.HTMLElement) {
      element.style.cssText += ";visibility:visible !important;";
    }

    return element;
  }

  // 注入命名空间支持
  private static injectNamespaceSupport() {
    document.createElement = (tagName: string) => {
      return document.createElementNS("http://www.w3.org/1999/xhtml", tagName);
    };
  }

  // 配置序列化（关键修复）
  private static setupSerialization() {
    window.XMLSerializer = class {
      serializeToString(node: Node) {
        const originalSerializer = new dom.window.XMLSerializer();
        let str = originalSerializer.serializeToString(node);

        // 保留 foreignObject 完整内容（不区分大小写）
        str = str.replace(
          /<foreignobject([^>]*)>([\s\S]*?)<\/foreignobject>/gi,
          (_, attrs, content) =>
            `<foreignObject${attrs}>${content}</foreignObject>`
        );

        // 保留所有 div 内容
        str = str.replace(
          /<div([^>]*)>([\s\S]*?)<\/div>/gi,
          (_, attrs, content) => `<div${attrs}>${content}</div>`
        );

        return str;
      }
    } as any;
  }

  // 注入全局样式
  private static injectGlobalStyles() {
    const style = document.createElement("style");
    style.textContent = `
      text, tspan, foreignObject div {
        fill: #333 !important;
        visibility: visible !important;
        font-family: Arial !important;
      }
      path, rect {
        stroke: #333 !important;
      }
    `;
    document.head.appendChild(style);
  }
}

// 初始化全局环境
Object.assign(global, {
  DOMParser,
  XMLSerializer,
  window,
  document,
  navigator: window.navigator,
  Node: window.Node,
  Element: window.Element,
  HTMLElement: window.HTMLElement,
  SVGElement: window.SVGElement,
});

// 初始化 Mermaid
let mermaid: any;
async function initialize() {
  if (!mermaid) {
    DOMEnhancer.init();
    mermaid = (await import("mermaid")).default;
    await mermaid.initialize({
      startOnLoad: false,
      securityLevel: "loose",
      fontFamily: "Arial",
      theme: "neutral",
    });
  }
}

// 渲染函数
async function render(code: string): Promise<string> {
  await initialize();
  const container = document.getElementById("container")!;
  container.innerHTML = "";

  try {
    const { svg } = await mermaid.render("mermaid-diagram", code);
    console.log(svg, "svg");
    // 最终清理（增强替换逻辑）
    // 安全处理函数
    const safeProcessSVG = (svg: string) => {
      const parser = new DOMParser(); // 现在使用JSDOM的解析器
      const doc = parser.parseFromString(svg, "image/svg+xml");
      const svgElement = doc.documentElement;

      // 智能设置属性
      if (!svgElement.hasAttribute("xmlns")) {
        svgElement.setAttribute("xmlns", "http://www.w3.org/2000/svg");
      }
      if (!svgElement.hasAttribute("viewBox")) {
        svgElement.setAttribute("viewBox", "0 0 800 600");
      }

      // 序列化时自动处理命名空间
      const serializer = new XMLSerializer();
      return serializer.serializeToString(doc.documentElement);
    };

    return safeProcessSVG(svg);
  } catch (err) {
    console.error("渲染失败:", err);
    throw err;
  }
}

// 启动 Worker
worker({ renderMermaid: render });
